package com.mo.tools.poi.watermark;


import com.microsoft.schemas.vml.*;
import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.HeaderStories;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

/**
 * 水印工具类
 * 支持给 Word(.docx)、Excel(.xlsx/.xls) 和 PowerPoint(.ppt/.pptx) 文件添加文字水印
 * Word水印保持平铺样式，支持换行显示
 *
 * @author mo
 * @since 1.0.0
 */
public class WatermarkUtil {

    // 水印默认配置
    private static final String DEFAULT_FONT = "PingFang SC";
    private static final int DEFAULT_FONT_SIZE = 28;
    private static final String DEFAULT_COLOR = "#B2B2B2";
    private static final float DEFAULT_OPACITY = 0.8f;
    private static final int WIDTH_PER_WORD = 10;

    // 常量定义
    private static final List<String> FILE_EXTENSION_EXCEL = Arrays.asList(".xlsx", ".xls");
    private static final String EXCEL_XLSX = ".xlsx";
    private static final String EXCEL_XLS = ".xls";
    private static final List<String> FILE_EXTENSION_WORD = Arrays.asList(".doc", ".docx");
    private static final String WORD_DOC = ".doc";
    private static final String WORD_DOCX = ".docx";
    private static final List<String> FILE_EXTENSION_PPT = Arrays.asList(".ppt", ".pptx");
    private static final String PPT_PPTX = ".pptx";
    private static final String PPT_PPT = ".ppt";
    private static final String WATERMARK_IMAGE_FORMAT = "png";
    private static final int MIN_IMAGE_WIDTH = 200;
    private static final int MIN_IMAGE_HEIGHT = 100;
    private static final int IMAGE_MARGIN = 50;
    private static final double ROTATION_ANGLE = -45.0;
    private static final String POSITION_ABSOLUTE = "absolute";
    private static final String FONT_FAMILY = "font-family:";
    private static final String FONT_SIZE_STYLE = "font-size:";

    // 多行水印配置
    private static final int LINE_SPACING = 5;

    // PPT水印配置
    private static final int PPT_WATERMARK_SPACING_X = 300;
    private static final int PPT_WATERMARK_SPACING_Y = 300;
    private static final double PPT_WATERMARK_SCALE = 0.3;

    private static final int PPT_FONT_SIZE = 17;

    // Excel水印配置
    private static final int EXCEL_WATERMARK_SPACING_X = 200;
    private static final int EXCEL_WATERMARK_SPACING_Y = 200;

    // 图片水印配置
    private static final List<String> FILE_EXTENSION_IMAGE = Arrays.asList(".jpg", ".jpeg", ".png", ".bmp", ".gif", ".tiff", ".tif");
    private static final String IMAGE_JPG = ".jpg";
    private static final String IMAGE_JPEG = ".jpeg";
    private static final String IMAGE_PNG = ".png";
    private static final String IMAGE_BMP = ".bmp";
    private static final String IMAGE_GIF = ".gif";
    private static final String IMAGE_TIFF = ".tiff";
    private static final String IMAGE_TIF = ".tif";
    
    // 图片水印默认位置和透明度
    private static final int IMAGE_WATERMARK_POSITION_X = 50;
    private static final int IMAGE_WATERMARK_POSITION_Y = 50;
    private static final float IMAGE_WATERMARK_OPACITY = 0.5f;
    private static final int IMAGE_WATERMARK_FONT_SIZE = 36;
    private static final int IMAGE_WATERMARK_MARGIN = 20;
    private static final int IMAGE_WATERMARK_SPACING_X = 600;
    private static final int IMAGE_WATERMARK_SPACING_Y = 400;

    /**
     * 给文件添加水印（使用默认样式）
     */
    public static void addWatermark(String inputFilePath, String outputFilePath, String watermarkText) {
        if (inputFilePath == null || outputFilePath == null || watermarkText == null) {
            throw new IllegalArgumentException("输入参数不能为空");
        }

        try {
            String fileName = inputFilePath.toLowerCase();

            if (FILE_EXTENSION_EXCEL.stream().anyMatch(fileName::endsWith)) {
                if (fileName.endsWith(EXCEL_XLSX)) {
                    addExcelXSSFWatermark(inputFilePath, outputFilePath, watermarkText);
                } else if (fileName.endsWith(EXCEL_XLS)) {
                    addExcelHSSFWatermark(inputFilePath, outputFilePath, watermarkText);
                }
            } else if (FILE_EXTENSION_WORD.stream().anyMatch(fileName::endsWith)) {
                if (fileName.endsWith(WORD_DOC)) {
                    // 使用HWPF处理DOC文件
                    addDocWatermark(inputFilePath, outputFilePath, watermarkText);
                }  else if (fileName.endsWith(WORD_DOCX)) {
                    addDocxWatermark(inputFilePath, outputFilePath, watermarkText);
                }
            } else if (FILE_EXTENSION_PPT.stream().anyMatch(fileName::endsWith)) {
                if (fileName.endsWith(PPT_PPTX)) {
                    addPptxWatermark(inputFilePath, outputFilePath, watermarkText);
                } else if (fileName.endsWith(PPT_PPT)) {
                    addPptWatermark(inputFilePath, outputFilePath, watermarkText);
                }
            } else if (FILE_EXTENSION_IMAGE.stream().anyMatch(fileName::endsWith)) {
                // 支持图片格式，使用默认字体和字体大小
                addImageWatermarkWithStyle(inputFilePath, outputFilePath, watermarkText, DEFAULT_FONT, IMAGE_WATERMARK_FONT_SIZE, DEFAULT_COLOR, MIN_IMAGE_WIDTH, MIN_IMAGE_HEIGHT);
            } else {
                throw new IllegalArgumentException("不支持的文件格式，仅支持 .xlsx, .xls, .docx, .ppt, .pptx, .jpg, .jpeg, .png, .bmp, .gif, .tiff, .tif 文件");
            }

        } catch (Exception e) {
            throw new RuntimeException("添加水印失败: " + e.getMessage(), e);
        }
    }

    /**
     * 高级配置：自定义水印样式
     */
    public static void addWatermarkWithStyle(String inputFilePath, String outputFilePath,
                                             String watermarkText, String fontName,
                                             Integer fontSize, String colorHex, Integer minWidth, Integer minHeight) {
        if (inputFilePath == null || outputFilePath == null || watermarkText == null) {
            throw new IllegalArgumentException("输入参数不能为空");
        }

        // 处理空值参数，使用默认值
        String finalFontName = (fontName == null || fontName.trim().isEmpty()) ? DEFAULT_FONT : fontName;
        int finalFontSize = (fontSize == null || fontSize <= 0) ? DEFAULT_FONT_SIZE : fontSize;
        String finalColorHex = (colorHex == null || colorHex.trim().isEmpty()) ? DEFAULT_COLOR : colorHex;
        
        // 根据文件类型确定默认的最小宽高
        minWidth = (minWidth == null || minWidth <= 0) ? MIN_IMAGE_WIDTH : minWidth;
        minHeight = (minHeight == null || minHeight <= 0) ? MIN_IMAGE_HEIGHT : minHeight;
        
        String fileName = inputFilePath.toLowerCase();

        try {
            if (FILE_EXTENSION_EXCEL.stream().anyMatch(fileName::endsWith)) {
                if (fileName.endsWith(EXCEL_XLSX)) {
                    addCustomExcelXSSFWatermark(inputFilePath, outputFilePath, watermarkText, finalFontName, finalFontSize, finalColorHex, minWidth, minHeight);
                } else if (fileName.endsWith(EXCEL_XLS)) {
                    addCustomExcelHSSFWatermark(inputFilePath, outputFilePath, watermarkText, finalFontName, finalFontSize, finalColorHex, minWidth, minHeight);
                } else {
                    addCustomExcelXSSFWatermark(inputFilePath, outputFilePath, watermarkText, finalFontName, finalFontSize, finalColorHex, minWidth, minHeight);
                }
            } else if (FILE_EXTENSION_WORD.stream().anyMatch(fileName::endsWith)) {
                if (fileName.endsWith(WORD_DOC)) {
                    addDocWatermark(inputFilePath, outputFilePath, watermarkText);
                } else if (fileName.endsWith(WORD_DOCX)) {
                    addDocxWatermark(inputFilePath, outputFilePath, watermarkText);
                }
            } else if (FILE_EXTENSION_PPT.stream().anyMatch(fileName::endsWith)) {
                if (fileName.endsWith(PPT_PPTX)) {
                    addCustomPptxWatermark(inputFilePath, outputFilePath, watermarkText, finalFontName, finalFontSize, finalColorHex, minWidth, minHeight);
                } else if (fileName.endsWith(PPT_PPT)) {
                    addCustomPptWatermark(inputFilePath, outputFilePath, watermarkText, finalFontName, finalFontSize, finalColorHex, minWidth, minHeight);
                }
            } else if (FILE_EXTENSION_IMAGE.stream().anyMatch(fileName::endsWith)) {
                addImageWatermarkWithStyle(inputFilePath, outputFilePath, watermarkText, finalFontName, finalFontSize, finalColorHex, minWidth, minHeight);
            } else {
                throw new IllegalArgumentException("不支持的文件格式，支持的文件格式包括：Excel(" + FILE_EXTENSION_EXCEL + ")、Word(" + FILE_EXTENSION_WORD + ")、PPT(" + FILE_EXTENSION_PPT + ")、图片(" + FILE_EXTENSION_IMAGE + ")");
            }

        } catch (Exception e) {
            throw new RuntimeException("自定义水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给Excel .xlsx 添加自定义样式的水印
     */
    private static void addCustomExcelXSSFWatermark(String inputPath, String outputPath,
                                                    String watermarkText, String fontName,
                                                    int fontSize, String colorHex, int defaultWidth, int defaultHeight) {
        try (FileInputStream fis = new FileInputStream(inputPath);
             XSSFWorkbook workbook = new XSSFWorkbook(fis);
             FileOutputStream fos = new FileOutputStream(outputPath)) {

            BufferedImage waterMarkImage = createWatermarkImage(watermarkText, fontName, fontSize, colorHex, defaultWidth, defaultHeight);
            ByteArrayOutputStream imageOs = new ByteArrayOutputStream();
            ImageIO.write(waterMarkImage, WATERMARK_IMAGE_FORMAT, imageOs);
            byte[] imageBytes = imageOs.toByteArray();

            int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG);
            Object pictureData = workbook.getAllPictures().get(pictureIdx);

            if (pictureData instanceof POIXMLDocumentPart) {
                POIXMLDocumentPart poixmlDocumentPart = (POIXMLDocumentPart) pictureData;
                for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                    XSSFSheet sheet = workbook.getSheetAt(i);
                    addWatermarkToExcelSheet(sheet, poixmlDocumentPart);
                }
            }

            workbook.write(fos);

        } catch (IOException e) {
            throw new RuntimeException("自定义Excel(.xlsx)水印添加失败: " + e.getMessage(), e);
        } catch (Exception e) {
            throw new RuntimeException("自定义Excel(.xlsx)水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给Excel .xls 添加自定义样式的水印
     */
    private static void addCustomExcelHSSFWatermark(String inputPath, String outputPath,
                                                    String watermarkText, String fontName,
                                                    int fontSize, String colorHex, int defaultWidth, int defaultHeight) {
        try (FileInputStream fis = new FileInputStream(inputPath);
             HSSFWorkbook workbook = new HSSFWorkbook(fis);
             FileOutputStream fos = new FileOutputStream(outputPath)) {

            BufferedImage waterMarkImage = createWatermarkImage(watermarkText, fontName, fontSize, colorHex, defaultWidth, defaultHeight);
            ByteArrayOutputStream imageOs = new ByteArrayOutputStream();
            ImageIO.write(waterMarkImage, WATERMARK_IMAGE_FORMAT, imageOs);
            byte[] imageBytes = imageOs.toByteArray();

            int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG);

            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                HSSFSheet sheet = workbook.getSheetAt(i);
                addWatermarkToHSSFSheet(sheet, pictureIdx);
            }

            workbook.write(fos);

        } catch (IOException e) {
            throw new RuntimeException("自定义Excel(.xls)水印添加失败: " + e.getMessage(), e);
        } catch (Exception e) {
            throw new RuntimeException("自定义Excel(.xls)水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给Word添加自定义样式的水印
     */
    private static void addCustomWordWatermark(String inputPath, String outputPath,
                                               String watermarkText, String fontName,
                                               int fontSize, String colorHex, int minWidth, int minHeight) {
        try (FileInputStream fis = new FileInputStream(inputPath);
             XWPFDocument document = new XWPFDocument(fis);
             FileOutputStream fos = new FileOutputStream(outputPath)) {

            if (watermarkText.contains("\n")) {
                addMultiLineWatermarkWithSpacing(document, watermarkText, colorHex, fontSize + "pt", "-45");
            } else {
                String customText = watermarkText + repeatString(" ", 16);
                customText = repeatString(customText, 10);

                String styleTop = "0pt";
                for (int lineIndex = -10; lineIndex < 5; lineIndex++) {
                    styleTop = 200 * lineIndex + "pt";
                    waterMarkDocXDocument(document, customText, styleTop, 1, colorHex, fontSize + "pt", "-45");
                }
            }

            document.write(fos);

        } catch (Exception e) {
            throw new RuntimeException("自定义Word水印添加失败: " + e.getMessage(), e);
        }
    }


    /**
     * 给PPT .pptx 文件添加水印 (XSLF) - 使用母版版式确保水印不可编辑
     */
    private static void addPptxWatermark(String inputPath, String outputPath, String watermarkText) {
        try (FileInputStream fis = new FileInputStream(inputPath);
             XMLSlideShow ppt = new XMLSlideShow(fis);
             FileOutputStream fos = new FileOutputStream(outputPath)) {

            // 创建水印图片
            BufferedImage waterMarkImage = createWatermarkImage(watermarkText, DEFAULT_FONT, PPT_FONT_SIZE, DEFAULT_COLOR, PPT_WATERMARK_SPACING_X, PPT_WATERMARK_SPACING_Y);
            ByteArrayOutputStream imageOs = new ByteArrayOutputStream();
            ImageIO.write(waterMarkImage, WATERMARK_IMAGE_FORMAT, imageOs);
            byte[] imageBytes = imageOs.toByteArray();

            // 将水印添加到母版版式（更有效的锁定方式）
            addWatermarkToPptxMaster(ppt, imageBytes);

            ppt.write(fos);

        } catch (IOException e) {
            throw new RuntimeException("PPT(.pptx)水印添加失败: " + e.getMessage(), e);
        } catch (Exception e) {
            throw new RuntimeException("PPT(.pptx)水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给PPT .ppt 文件添加水印 (HSLF) - 使用母版版式确保水印不可编辑
     */
    private static void addPptWatermark(String inputPath, String outputPath, String watermarkText) {
        try (FileInputStream fis = new FileInputStream(inputPath);
             HSLFSlideShow ppt = new HSLFSlideShow(fis);
             FileOutputStream fos = new FileOutputStream(outputPath)) {

            // 创建水印图片
            BufferedImage waterMarkImage = createWatermarkImage(watermarkText, DEFAULT_FONT, PPT_FONT_SIZE, DEFAULT_COLOR, PPT_WATERMARK_SPACING_X, PPT_WATERMARK_SPACING_Y);
            ByteArrayOutputStream imageOs = new ByteArrayOutputStream();
            ImageIO.write(waterMarkImage, WATERMARK_IMAGE_FORMAT, imageOs);
            byte[] imageBytes = imageOs.toByteArray();

            // 将水印添加到母版版式（更有效的锁定方式）
            addWatermarkToPptMaster(ppt, imageBytes);

            ppt.write(fos);

        } catch (IOException e) {
            throw new RuntimeException("PPT(.ppt)水印添加失败: " + e.getMessage(), e);
        } catch (Exception e) {
            throw new RuntimeException("PPT(.ppt)水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给PPT .pptx 文件添加自定义样式的水印
     */
    private static void addCustomPptxWatermark(String inputPath, String outputPath,
                                               String watermarkText, String fontName,
                                               int fontSize, String colorHex, int defaultWidth, int defaultHeight) {
        try (FileInputStream fis = new FileInputStream(inputPath);
             XMLSlideShow ppt = new XMLSlideShow(fis);
             FileOutputStream fos = new FileOutputStream(outputPath)) {

            // 创建自定义水印图片
            BufferedImage waterMarkImage = createWatermarkImage(watermarkText, fontName, fontSize, colorHex, defaultWidth, defaultHeight);
            ByteArrayOutputStream imageOs = new ByteArrayOutputStream();
            ImageIO.write(waterMarkImage, WATERMARK_IMAGE_FORMAT, imageOs);
            byte[] imageBytes = imageOs.toByteArray();

            // 将水印添加到母版版式（更有效的锁定方式）
            addWatermarkToPptxMaster(ppt, imageBytes);

            ppt.write(fos);

        } catch (IOException e) {
            throw new RuntimeException("自定义PPT(.pptx)水印添加失败: " + e.getMessage(), e);
        } catch (Exception e) {
            throw new RuntimeException("自定义PPT(.pptx)水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给PPT .ppt 文件添加自定义样式的水印
     */
    private static void addCustomPptWatermark(String inputPath, String outputPath,
                                               String watermarkText, String fontName,
                                               int fontSize, String colorHex, int defaultWidth, int defaultHeight) {
        try (FileInputStream fis = new FileInputStream(inputPath);
             HSLFSlideShow ppt = new HSLFSlideShow(fis);
             FileOutputStream fos = new FileOutputStream(outputPath)) {

            // 创建自定义水印图片
            BufferedImage waterMarkImage = createWatermarkImage(watermarkText, fontName, fontSize, colorHex, defaultWidth, defaultHeight);
            ByteArrayOutputStream imageOs = new ByteArrayOutputStream();
            ImageIO.write(waterMarkImage, WATERMARK_IMAGE_FORMAT, imageOs);
            byte[] imageBytes = imageOs.toByteArray();

            // 将水印添加到母版版式（更有效的锁定方式）
            addWatermarkToPptMaster(ppt, imageBytes);

            ppt.write(fos);

        } catch (IOException e) {
            throw new RuntimeException("自定义PPT(.ppt)水印添加失败: " + e.getMessage(), e);
        } catch (Exception e) {
            throw new RuntimeException("自定义PPT(.ppt)水印添加失败: " + e.getMessage(), e);
        }
    }


    /**
     * 给Excel .xlsx 文件添加水印 (XSSF)
     */
    private static void addExcelXSSFWatermark(String inputPath, String outputPath, String watermarkText) {
        try (FileInputStream fis = new FileInputStream(inputPath);
             XSSFWorkbook workbook = new XSSFWorkbook(fis);
             FileOutputStream fos = new FileOutputStream(outputPath)) {

            BufferedImage waterMarkImage = createWatermarkImage(watermarkText, DEFAULT_FONT, DEFAULT_FONT_SIZE, DEFAULT_COLOR, EXCEL_WATERMARK_SPACING_X, EXCEL_WATERMARK_SPACING_Y);
            ByteArrayOutputStream imageOs = new ByteArrayOutputStream();
            ImageIO.write(waterMarkImage, WATERMARK_IMAGE_FORMAT, imageOs);
            byte[] imageBytes = imageOs.toByteArray();

            int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG);
            Object pictureData = workbook.getAllPictures().get(pictureIdx);

            if (pictureData instanceof POIXMLDocumentPart) {
                POIXMLDocumentPart poixmlDocumentPart = (POIXMLDocumentPart) pictureData;

                for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                    XSSFSheet sheet = workbook.getSheetAt(i);
                    addWatermarkToExcelSheet(sheet, poixmlDocumentPart);
                }
            }

            workbook.write(fos);

        } catch (IOException e) {
            throw new RuntimeException("Excel水印添加失败: " + e.getMessage(), e);
        } catch (Exception e) {
            throw new RuntimeException("Excel水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给Excel .xls 文件添加水印 (HSSF) - 使用createPicture方法
     */
    private static void addExcelHSSFWatermark(String inputPath, String outputPath, String watermarkText) {
        try (FileInputStream fis = new FileInputStream(inputPath);
             HSSFWorkbook workbook = new HSSFWorkbook(fis);
             FileOutputStream fos = new FileOutputStream(outputPath)) {

            BufferedImage waterMarkImage = createWatermarkImage(watermarkText, DEFAULT_FONT, DEFAULT_FONT_SIZE, DEFAULT_COLOR, EXCEL_WATERMARK_SPACING_X, EXCEL_WATERMARK_SPACING_Y);
            ByteArrayOutputStream imageOs = new ByteArrayOutputStream();
            ImageIO.write(waterMarkImage, WATERMARK_IMAGE_FORMAT, imageOs);
            byte[] imageBytes = imageOs.toByteArray();

            int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG);

            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                HSSFSheet sheet = workbook.getSheetAt(i);
                addWatermarkToHSSFSheet(sheet, pictureIdx);
            }

            workbook.write(fos);

        } catch (IOException e) {
            throw new RuntimeException("Excel(.xls)水印添加失败: " + e.getMessage(), e);
        } catch (Exception e) {
            throw new RuntimeException("Excel(.xls)水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给HSSF工作表添加水印 - 使用createPicture方法
     */
    private static void addWatermarkToHSSFSheet(HSSFSheet sheet, int pictureIdx) {
        try {
            HSSFPatriarch patriarch = (HSSFPatriarch) sheet.createDrawingPatriarch();

            // 获取工作表实际尺寸
            int lastRowNum = Math.max(sheet.getLastRowNum(), 50);
            int lastColNum = 20; // 默认列数

            // 在多个位置添加水印实现平铺效果
            for (int row = 0; row < lastRowNum; row += 20) {  // 每20行一个水印
                for (int col = 0; col < lastColNum; col += 5) {  // 每5列一个水印
                    // 设置合理的锚点参数
                    int dx1 = 100;
                    int dy1 = 100;
                    int dx2 = Math.min(1023, 600);
                    int dy2 = Math.min(255, 200);

                    HSSFClientAnchor anchor = patriarch.createAnchor(
                            dx1, dy1, dx2, dy2,
                            col, row,           // 起始列和行
                            col + 3, row + 10   // 结束列和行
                    );

                    // 使用 MOVE_DONT_RESIZE 防止用户调整大小
                    anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
                    HSSFPicture picture = patriarch.createPicture(anchor, pictureIdx);

                    // 设置水印图片为锁定状态（不可编辑）
                    setPictureLocked(picture);
                }
            }

            // 保护工作表的对象，但允许单元格编辑
            // 这是HSSF中保护绘图对象的最有效方式
            sheet.protectSheet("");

        } catch (Exception e) {
            throw new RuntimeException("HSSF工作表水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 设置Excel图片为锁定状态（不可编辑）
     */
    private static void setPictureLocked(HSSFPicture picture) {
        try {
            // 使用反射获取 getObjRecord 方法
            Method getObjRecordMethod = HSSFShape.class.getDeclaredMethod("getObjRecord");
            getObjRecordMethod.setAccessible(true);
            ObjRecord objRecord = (ObjRecord) getObjRecordMethod.invoke(picture);

            if (objRecord != null) {
                // 查找 CommonObjectDataSubRecord 并设置锁定属性
                for (Object subRecordObj : objRecord.getSubRecords()) {
                    if (subRecordObj instanceof CommonObjectDataSubRecord) {
                        CommonObjectDataSubRecord commonObjData = (CommonObjectDataSubRecord) subRecordObj;
                        commonObjData.setLocked(true);  // 设置为锁定状态
                        break;
                    }
                }
            }
        } catch (Exception e) {
            // 忽略异常，不影响水印添加功能
            System.err.println("无法设置图片锁定属性: " + e.getMessage());
        }
    }

    /**
     * 给Excel工作表添加水印 (XSSF)
     */
    private static void addWatermarkToExcelSheet(XSSFSheet sheet, POIXMLDocumentPart poixmlDocumentPart) {
        try {
            PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
            String relType = XSSFRelation.IMAGES.getRelation();

            PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn,
                    TargetMode.INTERNAL, relType, null);

            sheet.getCTWorksheet().addNewPicture().setId(pr.getId());

        } catch (Exception e) {
            throw new RuntimeException("Excel工作表水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 创建水印图片
     */
    private static BufferedImage createWatermarkImage(String watermarkText, String fontName,
                                                      int fontSize, String colorHex, int defaultWidth, int defaultHeight) {
        String[] lines = watermarkText.split("\n");
        int[] dimensions = calculateTextDimensionsWithLineBreak(lines, fontName, fontSize);

        // 使用配置的默认大小作为基础尺寸
        int defaultSize = Math.max(defaultWidth, defaultHeight);
        
        // 计算文字需要的最大尺寸（考虑旋转后的尺寸）
        int textMaxDimension = Math.max(dimensions[0], dimensions[1]);
        
        // 优先使用默认大小，只有当文字尺寸超过默认大小时才使用文字尺寸
        int finalSize = defaultSize;
        if (textMaxDimension > defaultSize) {
            finalSize = textMaxDimension;
        }
        
        // 应用缩放比例
        finalSize = (int) (finalSize * PPT_WATERMARK_SCALE);
        
        // 确保最小尺寸
        finalSize = Math.max(MIN_IMAGE_WIDTH, finalSize);
        finalSize = Math.max(MIN_IMAGE_HEIGHT, finalSize);
        
        int width = finalSize;
        int height = finalSize;

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = image.createGraphics();

        try {
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, DEFAULT_OPACITY));

            Font font = new Font(fontName, Font.PLAIN, fontSize);
            g2d.setFont(font);
            Color color = Color.decode(colorHex);
            g2d.setColor(color);

            FontMetrics fontMetrics = g2d.getFontMetrics();
            int textHeight = fontMetrics.getHeight();
            int totalTextHeight = textHeight * lines.length;
            int startY = (height - totalTextHeight) / 2 + fontMetrics.getAscent();

            g2d.rotate(Math.toRadians(ROTATION_ANGLE), width / 2.0, height / 2.0);

            for (int i = 0; i < lines.length; i++) {
                int textWidth = fontMetrics.stringWidth(lines[i]);
                int x = (width - textWidth) / 2;
                int y = startY + i * textHeight;
                g2d.drawString(lines[i], x, y);
            }
        } finally {
            g2d.dispose();
        }

        return image;
    }

    /**
     * 计算带换行文本的尺寸
     */
    private static int[] calculateTextDimensionsWithLineBreak(String[] lines, String fontName, int fontSize) {
        Font font = new Font(fontName, Font.PLAIN, fontSize);
        FontRenderContext frc = new FontRenderContext(new AffineTransform(), true, true);

        double maxWidth = 0;
        for (String line : lines) {
            Rectangle2D bounds = font.getStringBounds(line, frc);
            if (bounds.getWidth() > maxWidth) {
                maxWidth = bounds.getWidth();
            }
        }

        Rectangle2D sampleLineBounds = font.getStringBounds("Ay", frc);
        double lineHeight = sampleLineBounds.getHeight();
        double totalHeight = lineHeight * lines.length;

        double rotatedWidth = Math.abs(maxWidth * Math.cos(Math.toRadians(45))) +
                Math.abs(totalHeight * Math.sin(Math.toRadians(45)));
        double rotatedHeight = Math.abs(maxWidth * Math.sin(Math.toRadians(45))) +
                Math.abs(totalHeight * Math.cos(Math.toRadians(45)));

        return new int[]{(int) Math.ceil(rotatedWidth), (int) Math.ceil(rotatedHeight)};
    }

    /**
     * 给Word .doc 文件添加水印 (HWPF)
     */
    private static void addDocWatermark(String inputPath, String outputPath, String watermarkText) {
        try (FileInputStream fis = new FileInputStream(inputPath);
             HWPFDocument document = new HWPFDocument(fis);
             FileOutputStream fos = new FileOutputStream(outputPath)) {

            // 创建水印图片
            BufferedImage waterMarkImage = createWatermarkImageForDoc(watermarkText, DEFAULT_FONT, DEFAULT_FONT_SIZE, DEFAULT_COLOR);
            ByteArrayOutputStream imageOs = new ByteArrayOutputStream();
            ImageIO.write(waterMarkImage, WATERMARK_IMAGE_FORMAT, imageOs);
            byte[] imageBytes = imageOs.toByteArray();

            // 使用正确的HWPF方法添加水印
            addWatermarkToDocHeader(document, imageBytes);

            document.write(fos);
        } catch (Exception e) {
            throw new RuntimeException("Word(.doc)水印添加失败: " + e.getMessage(), e);
        }
    }
    /**
     * 通过页眉添加水印到.doc文件
     */
    private static void addWatermarkToDocHeader(HWPFDocument document, byte[] imageBytes) {
        try {
            // 获取文档范围
            Range range = document.getRange();

            // 创建页眉
            HeaderStories headerStories = new HeaderStories(document);

            // 为所有页眉类型添加水印
            addImageToHeader(document, headerStories.getFirstHeader(), imageBytes);
            addImageToHeader(document, headerStories.getEvenHeader(), imageBytes);
            addImageToHeader(document, headerStories.getOddHeader(), imageBytes);

        } catch (Exception e) {
            System.err.println("通过页眉添加水印失败: " + e.getMessage());
        }
    }

    /**
     * 在页眉中添加图片
     */
    private static void addImageToHeader(HWPFDocument document, String headerText, byte[] imageBytes) {
        try {
            // 使用反射获取内部方法
            Method addPictureMethod = document.getClass().getDeclaredMethod("addPicture", byte[].class, int.class);
            addPictureMethod.setAccessible(true);

            // 添加图片
            Object picture = addPictureMethod.invoke(document, imageBytes, PictureType.PNG);

            // 获取图片索引
            Method getPictureIndexMethod = picture.getClass().getDeclaredMethod("getIndex");
            getPictureIndexMethod.setAccessible(true);
            int pictureIndex = (Integer) getPictureIndexMethod.invoke(picture);

            // 将图片添加到页眉
            Method addPictureToHeaderMethod = document.getClass().getDeclaredMethod("addPictureToHeader", int.class, int.class);
            addPictureToHeaderMethod.setAccessible(true);
            addPictureToHeaderMethod.invoke(document, pictureIndex, 0); // 0表示页眉

        } catch (Exception e) {
            System.err.println("添加图片到页眉失败: " + e.getMessage());
        }
    }
    

    /**
     * 为.doc文件创建水印图片
     */
    private static BufferedImage createWatermarkImageForDoc(String watermarkText, String fontName, int fontSize, String colorHex) {
        // 单行文本处理
        String[] lines = watermarkText.split("\n");
        String singleLine = lines.length > 0 ? lines[0] : watermarkText;

        int[] dimensions = calculateTextDimensions(singleLine, fontName, fontSize);

        int width = Math.max(MIN_IMAGE_WIDTH, dimensions[0] + IMAGE_MARGIN * 2);
        int height = Math.max(MIN_IMAGE_HEIGHT, dimensions[1] + IMAGE_MARGIN * 2);

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = image.createGraphics();

        try {
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, DEFAULT_OPACITY));

            Font font = new Font(fontName, Font.PLAIN, fontSize);
            g2d.setFont(font);
            Color color = Color.decode(colorHex);
            g2d.setColor(color);

            FontMetrics fontMetrics = g2d.getFontMetrics();
            int textHeight = fontMetrics.getHeight();
            int startY = (height - textHeight) / 2 + fontMetrics.getAscent();

            g2d.rotate(Math.toRadians(ROTATION_ANGLE), width / 2.0, height / 2.0);
            g2d.drawString(singleLine, (width - fontMetrics.stringWidth(singleLine)) / 2, startY);

        } finally {
            g2d.dispose();
        }

        return image;
    }

    /**
     * 计算文本的尺寸（考虑旋转45度后的边界）
     */
    private static int[] calculateTextDimensions(String text, String fontName, int fontSize) {
        Font font = new Font(fontName, Font.PLAIN, fontSize);
        FontRenderContext frc = new FontRenderContext(new AffineTransform(), true, true);
        Rectangle2D bounds = font.getStringBounds(text, frc);

        double width = bounds.getWidth();
        double height = bounds.getHeight();

        double rotatedWidth = Math.abs(width * Math.cos(Math.toRadians(45))) +
                Math.abs(height * Math.sin(Math.toRadians(45)));
        double rotatedHeight = Math.abs(width * Math.sin(Math.toRadians(45))) +
                Math.abs(height * Math.cos(Math.toRadians(45)));

        return new int[]{(int) Math.ceil(rotatedWidth), (int) Math.ceil(rotatedHeight)};
    }



    /**
     * 使用博客中的逻辑给Word文件添加水印
     */
    private static void addDocxWatermark(String inputPath, String outputPath, String watermarkText) {
        try (FileInputStream fis = new FileInputStream(inputPath);
             XWPFDocument document = new XWPFDocument(fis);
             FileOutputStream fos = new FileOutputStream(outputPath)) {

            if (watermarkText.contains("\n")) {
                addMultiLineWatermarkWithSpacing(document, watermarkText, DEFAULT_COLOR,
                        DEFAULT_FONT_SIZE + "pt", "-45");
            } else {
                addSingleLineWatermark(document, watermarkText, DEFAULT_COLOR,
                        DEFAULT_FONT_SIZE + "pt", "-45");
            }

            document.write(fos);

        } catch (IOException e) {
            throw new RuntimeException("Word水印添加失败: " + e.getMessage(), e);
        } catch (Exception e) {
            throw new RuntimeException("Word水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 添加多行水印
     */
    private static void addMultiLineWatermarkWithSpacing(XWPFDocument docx, String watermarkText,
                                                       String fontColor, String fontSize, String styleRotation) {
        String[] lines = watermarkText.split("\n");

        for (int lineIndex = -2; lineIndex < 4; lineIndex++) {
            int lineTop = 240 * lineIndex;
            for (int i = 0; i < lines.length; i++) {
                String line = lines[i].trim();
                if (!line.isEmpty()) {
                    int currentLineTop = lineTop + i * (LINE_SPACING + 20);
                    String processedText = line + repeatString(" ", 20);
                    processedText = repeatString(processedText, 3);

                    waterMarkDocXDocument(docx, processedText, currentLineTop + "pt", 1, fontColor, fontSize, styleRotation);
                }
            }
        }
    }

    /**
     * 添加单行水印
     */
    private static void addSingleLineWatermark(XWPFDocument docx, String customText,
                                              String fontColor, String fontSize, String styleRotation) {
        String processedText = customText + repeatString(" ", 20);
        processedText = repeatString(processedText, 3);

        String styleTop = "0pt";
        for (int lineIndex = -2; lineIndex < 4; lineIndex++) {
            styleTop = (240 * lineIndex) + "pt";
            waterMarkDocXDocument(docx, processedText, styleTop, 1, fontColor, fontSize, styleRotation);
        }
    }

    /**
     * 将指定的字符串重复repeats次
     */
    private static String repeatString(String pattern, int repeats) {
        StringBuilder buffer = new StringBuilder(pattern.length() * repeats);
        for (int i = 0; i < repeats; i++) {
            buffer.append(pattern);
        }
        return buffer.toString();
    }

    /**
     * 为文档添加水印
     */
    private static void waterMarkDocXDocument(XWPFDocument doc, String customText, String styleTop,
                                              int type, String fontColor, String fontSize, String rotation) {
        XWPFHeader header = doc.createHeader(org.apache.poi.wp.usermodel.HeaderFooterType.DEFAULT);

        int size = header.getParagraphs().size();
        if (size == 0) {
            header.createParagraph();
        }

        CTP ctp = header.getParagraphArray(0).getCTP();
        byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
        byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
        ctp.setRsidP(rsidr);
        ctp.setRsidRDefault(rsidrdefault);

        CTPPr ppr = ctp.addNewPPr();
        ppr.addNewPStyle().setVal("Header");

        CTR ctr = ctp.addNewR();
        CTRPr ctrpr = ctr.addNewRPr();
        ctrpr.addNewNoProof();

        CTGroup group = CTGroup.Factory.newInstance();
        CTShapetype shapetype = group.addNewShapetype();
        CTTextPath shapeTypeTextPath = shapetype.addNewTextpath();
        shapeTypeTextPath.setOn(STTrueFalse.T);
        shapeTypeTextPath.setFitshape(STTrueFalse.T);

        CTShape shape = group.addNewShape();
        shape.setId("PowerPlusWaterMarkObject");
        shape.setSpid("_x0000_s102");
        shape.setType("#_x0000_t136");

        if (type != 2) {
            shape.setStyle(getShapeStyle(customText, styleTop, rotation));
        } else {
            shape.setStyle(getShapeStyle());
        }

        shape.setFillcolor(fontColor);
        shape.setStroked(STTrueFalse.FALSE);

        CTTextPath shapeTextPath = shape.addNewTextpath();
        shapeTextPath.setStyle(FONT_FAMILY + DEFAULT_FONT + ";" + FONT_SIZE_STYLE + fontSize);
        shapeTextPath.setString(customText);

        CTPicture pict = ctr.addNewPict();
        pict.set(group);
    }

    /**
     * 构建Shape的样式参数（平铺水印）
     */
    private static String getShapeStyle(String customText, String styleTop, String styleRotation) {
        StringBuilder sb = new StringBuilder();
        sb.append("position: ").append(POSITION_ABSOLUTE);
        sb.append(";width: ").append(customText.length() * WIDTH_PER_WORD).append("pt");
        sb.append(";height: ").append("20pt");
        sb.append(";z-index: ").append("-251654144");
        sb.append(";mso-wrap-edited: ").append("f");
        sb.append(";margin-top: ").append(styleTop);
        sb.append(";mso-position-horizontal-relative: ").append("margin");
        sb.append(";mso-position-vertical-relative: ").append("margin");
        sb.append(";mso-position-vertical: ").append("left");
        sb.append(";mso-position-horizontal: ").append("center");
        sb.append(";rotation: ").append(styleRotation);
        return sb.toString();
    }

    /**
     * 构建Shape的样式参数（单个水印）
     */
    private static String getShapeStyle() {
        StringBuilder sb = new StringBuilder();
        sb.append("position: ").append(POSITION_ABSOLUTE);
        sb.append(";left: ").append("opt");
        sb.append(";width: ").append("500pt");
        sb.append(";height: ").append("150pt");
        sb.append(";z-index: ").append("-251654144");
        sb.append(";mso-wrap-edited: ").append("f");
        sb.append(";margin-left: ").append("-50pt");
        sb.append(";margin-top: ").append("270pt");
        sb.append(";mso-position-horizontal-relative: ").append("margin");
        sb.append(";mso-position-vertical-relative: ").append("margin");
        sb.append(";mso-width-relative: ").append("page");
        sb.append(";mso-height-relative: ").append("page");
        sb.append(";rotation: ").append("-2949120f");
        return sb.toString();
    }

    /**
     * 将水印添加到PPTX母版版式（真正的锁定方案）
     */
    private static void addWatermarkToPptxMaster(XMLSlideShow ppt, byte[] imageBytes) {
        try {
            // 获取所有母版
            for (XSLFSlideMaster master : ppt.getSlideMasters()) {
                // 获取母版版式
                for (XSLFSlideLayout layout : master.getSlideLayouts()) {
                    // 添加图片到母版版式
                    XSLFPictureData pictureData = ppt.addPicture(imageBytes, PictureData.PictureType.PNG);
                    
                    // 获取母版版式尺寸
                    Dimension pageSize = layout.getSlideShow().getPageSize();
                    int layoutWidth = (int) pageSize.getWidth();
                    int layoutHeight = (int) pageSize.getHeight();
                    
                    // 获取水印图片尺寸
                    BufferedImage watermarkImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
                    int watermarkWidth = watermarkImage.getWidth();
                    int watermarkHeight = watermarkImage.getHeight();
                    
                    // 创建左下角水印
                    XSLFPictureShape bottomLeftShape = layout.createPicture(pictureData);
                    int bottomLeftX = 20; // 距离左边20像素
                    int bottomLeftY = layoutHeight - watermarkHeight - 20; // 距离底部20像素
                    bottomLeftShape.setAnchor(new Rectangle(bottomLeftX, bottomLeftY, watermarkWidth, watermarkHeight));
                    
                    // 创建右上角水印
                    XSLFPictureShape topRightShape = layout.createPicture(pictureData);
                    int topRightX = layoutWidth - watermarkWidth - 20; // 距离右边20像素
                    int topRightY = 20; // 距离顶部20像素
                    topRightShape.setAnchor(new Rectangle(topRightX, topRightY, watermarkWidth, watermarkHeight));
                    
                    // 设置母版版式中的水印为背景层（不可编辑）
                    bottomLeftShape.setAnchor(new Rectangle(bottomLeftX, bottomLeftY, watermarkWidth, watermarkHeight));
                    topRightShape.setAnchor(new Rectangle(topRightX, topRightY, watermarkWidth, watermarkHeight));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("PPTX母版版式水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 将水印添加到PPT母版版式（真正的锁定方案）
     * 参考PPTX逻辑：在母版上添加水印，确保所有幻灯片都有水印且不可编辑
     */
    private static void addWatermarkToPptMaster(HSLFSlideShow ppt, byte[] imageBytes) {
        try {
            // 获取所有母版
            List<HSLFSlideMaster> masters = ppt.getSlideMasters();
            
            // 在HSLF中，通过母版添加水印，确保所有基于该母版的幻灯片都有水印
            for (HSLFSlideMaster master : masters) {
                // 在母版上添加水印
                addWatermarkToMasterSlide(master, imageBytes, ppt.getPageSize());
            }
            
        } catch (Exception e) {
            // 如果母版添加失败，回退到幻灯片级别
            addWatermarkToAllSlidesDirectly(ppt, imageBytes);
        }
    }
    
    /**
     * 在母版上添加水印
     */
    private static void addWatermarkToMasterSlide(HSLFSlideMaster master, byte[] imageBytes, java.awt.Dimension pageSize) {
        try {
            // 添加图片到母版
            HSLFPictureData pictureData = master.getSlideShow().addPicture(imageBytes, PictureData.PictureType.PNG);
            
            // 获取水印图片尺寸
            BufferedImage watermarkImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
            int watermarkWidth = watermarkImage.getWidth();
            int watermarkHeight = watermarkImage.getHeight();
            
            // 与PPTX保持一致：只在左下角和右上角添加水印
            int[][] positions = {
                {20, pageSize.height - watermarkHeight - 20}, // 左下角
                {pageSize.width - watermarkWidth - 20, 20}    // 右上角
            };
            
            for (int[] pos : positions) {
                HSLFPictureShape shape = master.createPicture(pictureData);
                shape.setAnchor(new java.awt.Rectangle(pos[0], pos[1], watermarkWidth, watermarkHeight));
                
                // 设置水印为背景层（不可编辑）
                shape.setLineColor(null);
                shape.setLineWidth(0.0);

            }
        } catch (Exception e) {
            throw new RuntimeException("母版水印添加失败", e);
        }
    }
    
    /**
     * 回退方案：直接在所有幻灯片上添加水印
     */
    private static void addWatermarkToAllSlidesDirectly(HSLFSlideShow ppt, byte[] imageBytes) {
        try {
            // 添加图片到PPT
            HSLFPictureData pictureData = ppt.addPicture(imageBytes, PictureData.PictureType.PNG);
            
            // 获取PPT尺寸
            java.awt.Dimension pageSize = ppt.getPageSize();
            int layoutWidth = pageSize.width;
            int layoutHeight = pageSize.height;
            
            // 获取水印图片尺寸
            BufferedImage watermarkImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
            int watermarkWidth = watermarkImage.getWidth();
            int watermarkHeight = watermarkImage.getHeight();
            
            // 获取所有幻灯片
            List<HSLFSlide> allSlides = ppt.getSlides();
            
            // 在所有幻灯片上添加水印
            for (HSLFSlide slide : allSlides) {
                addWatermarkToSlideAsBackground(slide, pictureData, layoutWidth, layoutHeight, watermarkWidth, watermarkHeight);
            }
        } catch (Exception e) {
            throw new RuntimeException("幻灯片级别水印添加失败", e);
        }
    }

    
    /**
     * 在幻灯片上添加水印作为背景层
     */
    private static void addWatermarkToSlideAsBackground(HSLFSlide slide, HSLFPictureData pictureData, 
                                                     int layoutWidth, int layoutHeight, 
                                                     int watermarkWidth, int watermarkHeight) {
        try {
            // 创建左下角水印
            HSLFPictureShape bottomLeftShape = slide.createPicture(pictureData);
            int bottomLeftX = 20; // 距离左边20像素
            int bottomLeftY = layoutHeight - watermarkHeight - 20; // 距离底部20像素
            bottomLeftShape.setAnchor(new java.awt.Rectangle(bottomLeftX, bottomLeftY, watermarkWidth, watermarkHeight));
            
            // 创建右上角水印
            HSLFPictureShape topRightShape = slide.createPicture(pictureData);
            int topRightX = layoutWidth - watermarkWidth - 20; // 距离右边20像素
            int topRightY = 20; // 距离顶部20像素
            topRightShape.setAnchor(new java.awt.Rectangle(topRightX, topRightY, watermarkWidth, watermarkHeight));
            
            // 设置水印为背景层（不可编辑）
            bottomLeftShape.setLineColor(null);
            topRightShape.setLineColor(null);
            
            // 在HSLF中，通过设置无边框和透明背景来模拟背景层效果
            bottomLeftShape.setLineWidth(0.0);
            topRightShape.setLineWidth(0.0);
            
        } catch (Exception e) {
            throw new RuntimeException("幻灯片水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给图片文件添加水印（使用默认样式）
     */
    private static void addImageWatermark(String inputPath, String outputPath, String watermarkText) {
        try {
            addImageWatermarkWithStyle(inputPath, outputPath, watermarkText, 
                    DEFAULT_FONT, DEFAULT_FONT_SIZE, DEFAULT_COLOR, 
                    IMAGE_WATERMARK_POSITION_X, IMAGE_WATERMARK_POSITION_Y);
        } catch (Exception e) {
            throw new RuntimeException("图片水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给图片文件添加平铺水印（旋转-45度，使用默认样式）
     */
    private static void addTiledImageWatermarkDefault(String inputPath, String outputPath, String watermarkText) {
        try {
            addTiledImageWatermark(inputPath, outputPath, watermarkText, 
                    DEFAULT_FONT, DEFAULT_FONT_SIZE, DEFAULT_COLOR);
        } catch (Exception e) {
            throw new RuntimeException("图片平铺水印添加失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给图片文件添加自定义样式的水印（支持旋转和平铺）
     */
    private static void addImageWatermarkWithStyle(String inputPath, String outputPath, String watermarkText,
                                                   String fontName, int fontSize, String colorHex,
                                                   int positionX, int positionY) {
        try {
            // 读取原始图片
            BufferedImage originalImage = ImageIO.read(new File(inputPath));
            if (originalImage == null) {
                throw new IllegalArgumentException("无法读取图片文件: " + inputPath);
            }

            // 根据图片格式选择不同的处理方法
            String fileName = inputPath.toLowerCase();
            BufferedImage watermarkedImage;
            
            if (fileName.endsWith(IMAGE_JPG) || fileName.endsWith(IMAGE_JPEG)) {
                // JPG格式：使用RGB模式，不支持透明度
                watermarkedImage = addWatermarkToJpgImage(originalImage, watermarkText, 
                        fontName, fontSize, colorHex, positionX, positionY);
            } else if (fileName.endsWith(IMAGE_PNG)) {
                // PNG格式：支持透明度
                watermarkedImage = addWatermarkToPngImage(originalImage, watermarkText, 
                        fontName, fontSize, colorHex, positionX, positionY);
            } else if (fileName.endsWith(IMAGE_GIF)) {
                // GIF格式：可能需要特殊处理
                watermarkedImage = addWatermarkToGifImage(originalImage, watermarkText, 
                        fontName, fontSize, colorHex, positionX, positionY);
            } else {
                // 其他格式：使用通用方法
                watermarkedImage = addWatermarkToImage(originalImage, watermarkText, 
                        fontName, fontSize, colorHex, positionX, positionY);
            }

            // 获取原始图片格式
            String formatName = getImageFormatName(inputPath);
            
            // 保存带水印的图片，保持原始格式
            ImageIO.write(watermarkedImage, formatName, new File(outputPath));

        } catch (IOException e) {
            throw new RuntimeException("图片水印处理失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给图片添加平铺水印（旋转-45度）
     */
    private static void addTiledImageWatermark(String inputPath, String outputPath, String watermarkText,
                                              String fontName, int fontSize, String colorHex) {
        try {
            // 读取原始图片
            BufferedImage originalImage = ImageIO.read(new File(inputPath));
            if (originalImage == null) {
                throw new IllegalArgumentException("无法读取图片文件: " + inputPath);
            }

            // 根据图片格式选择不同的处理方法
            String fileName = inputPath.toLowerCase();
            BufferedImage watermarkedImage;
            
            if (fileName.endsWith(IMAGE_JPG) || fileName.endsWith(IMAGE_JPEG)) {
                // JPG格式：使用RGB模式，不支持透明度
                watermarkedImage = addTiledWatermarkToJpgImage(originalImage, watermarkText, 
                        fontName, fontSize, colorHex);
            } else if (fileName.endsWith(IMAGE_PNG)) {
                // PNG格式：支持透明度
                watermarkedImage = addTiledWatermarkToPngImage(originalImage, watermarkText, 
                        fontName, fontSize, colorHex);
            } else if (fileName.endsWith(IMAGE_GIF)) {
                // GIF格式：可能需要特殊处理
                watermarkedImage = addTiledWatermarkToGifImage(originalImage, watermarkText, 
                        fontName, fontSize, colorHex);
            } else {
                // 其他格式：使用通用方法
                watermarkedImage = addTiledWatermarkToImage(originalImage, watermarkText, 
                        fontName, fontSize, colorHex);
            }

            // 获取原始图片格式
            String formatName = getImageFormatName(inputPath);
            
            // 保存带水印的图片，保持原始格式
            ImageIO.write(watermarkedImage, formatName, new File(outputPath));

        } catch (IOException e) {
            throw new RuntimeException("图片平铺水印处理失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给JPG图片添加水印（不支持透明度）
     */
    private static BufferedImage addWatermarkToJpgImage(BufferedImage originalImage, String watermarkText,
                                                       String fontName, int fontSize, String colorHex,
                                                       int positionX, int positionY) {
        // JPG格式使用RGB模式，不支持透明度
        BufferedImage watermarkedImage = new BufferedImage(
                originalImage.getWidth(), 
                originalImage.getHeight(), 
                BufferedImage.TYPE_INT_RGB
        );

        Graphics2D g2d = watermarkedImage.createGraphics();
        
        try {
            // 绘制原始图片
            g2d.drawImage(originalImage, 0, 0, null);
            
            // 设置水印样式（JPG不支持透明度，使用不透明度1.0）
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));

            Font font = new Font(fontName, Font.PLAIN, fontSize);
            g2d.setFont(font);
            Color color = Color.decode(colorHex);
            g2d.setColor(color);

            // 实现旋转-45度和平铺效果（与Word/Excel保持一致）
            FontMetrics fontMetrics = g2d.getFontMetrics();
            
            // 检查水印文本是否包含换行符
            String[] watermarkLines = watermarkText.split("\\n");
            
            // 计算多行文本的总高度和最大宽度
            int maxLineWidth = 0;
            int totalTextHeight = 0;
            for (String line : watermarkLines) {
                int lineWidth = fontMetrics.stringWidth(line);
                if (lineWidth > maxLineWidth) {
                    maxLineWidth = lineWidth;
                }
                totalTextHeight += fontMetrics.getHeight();
            }
            
            // 动态计算平铺间距：根据图片大小调整间距
            int baseSpacingX = 300; // 基础水平间距
            int baseSpacingY = 300; // 基础垂直间距
            
            // 根据图片大小调整间距（大图片使用较大间距，小图片使用较小间距）
            int imageWidth = watermarkedImage.getWidth();
            int imageHeight = watermarkedImage.getHeight();
            
            // 计算动态间距：图片越大，间距越大
            int dynamicSpacingX = baseSpacingX + (imageWidth / 800) * 100; // 每800像素增加100间距
            int dynamicSpacingY = baseSpacingY + (imageHeight / 600) * 100; // 每600像素增加100间距
            
            // 确保间距不小于文本尺寸
            int spacingX = Math.max(maxLineWidth + dynamicSpacingX, maxLineWidth + baseSpacingX);
            int spacingY = Math.max(totalTextHeight + dynamicSpacingY, totalTextHeight + baseSpacingY);
            
            // 在整个图片上平铺水印，从左边距50像素开始
            int startX = 50; // 左边距50像素
            for (int x = startX - watermarkedImage.getWidth(); x < watermarkedImage.getWidth() * 2; x += spacingX) {
                for (int y = -watermarkedImage.getHeight(); y < watermarkedImage.getHeight() * 2; y += spacingY) {
                    // 保存原始变换
                    AffineTransform originalTransform = g2d.getTransform();
                    
                    // 计算旋转中心点
                    int centerX = x + maxLineWidth / 2;
                    int centerY = y + totalTextHeight / 2;
                    
                    // 应用旋转-45度
                    g2d.rotate(Math.toRadians(-45), centerX, centerY);
                    
                    // 绘制多行水印文本
                    int currentY = y;
                    for (String line : watermarkLines) {
                        g2d.drawString(line, x, currentY + fontMetrics.getHeight());
                        currentY += fontMetrics.getHeight();
                    }
                    
                    // 恢复原始变换
                    g2d.setTransform(originalTransform);
                }
            }
            
        } finally {
            g2d.dispose();
        }
        
        return watermarkedImage;
    }

    /**
     * 给PNG图片添加水印（支持透明度）
     */
    private static BufferedImage addWatermarkToPngImage(BufferedImage originalImage, String watermarkText,
                                                       String fontName, int fontSize, String colorHex,
                                                       int positionX, int positionY) {
        // PNG格式使用ARGB模式，支持透明度
        BufferedImage watermarkedImage = new BufferedImage(
                originalImage.getWidth(), 
                originalImage.getHeight(), 
                BufferedImage.TYPE_INT_ARGB
        );

        Graphics2D g2d = watermarkedImage.createGraphics();
        
        try {
            // 绘制原始图片
            g2d.drawImage(originalImage, 0, 0, null);
            
            // 设置水印样式（PNG支持透明度）
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, IMAGE_WATERMARK_OPACITY));

            Font font = new Font(fontName, Font.PLAIN, fontSize);
            g2d.setFont(font);
            Color color = Color.decode(colorHex);
            g2d.setColor(color);

            // 实现旋转-45度和平铺效果（与Word/Excel保持一致）
            FontMetrics fontMetrics = g2d.getFontMetrics();
            
            // 检查水印文本是否包含换行符
            String[] watermarkLines = watermarkText.split("\\n");
            
            // 计算多行文本的总高度和最大宽度
            int maxLineWidth = 0;
            int totalTextHeight = 0;
            for (String line : watermarkLines) {
                int lineWidth = fontMetrics.stringWidth(line);
                if (lineWidth > maxLineWidth) {
                    maxLineWidth = lineWidth;
                }
                totalTextHeight += fontMetrics.getHeight();
            }
            
            // 动态计算平铺间距：根据图片大小调整间距
            int baseSpacingX = 300; // 基础水平间距
            int baseSpacingY = 300; // 基础垂直间距
            
            // 根据图片大小调整间距（大图片使用较大间距，小图片使用较小间距）
            int imageWidth = watermarkedImage.getWidth();
            int imageHeight = watermarkedImage.getHeight();
            
            // 计算动态间距：图片越大，间距越大
            int dynamicSpacingX = baseSpacingX + (imageWidth / 800) * 100; // 每800像素增加100间距
            int dynamicSpacingY = baseSpacingY + (imageHeight / 600) * 100; // 每600像素增加100间距
            
            // 确保间距不小于文本尺寸
            int spacingX = Math.max(maxLineWidth + dynamicSpacingX, maxLineWidth + baseSpacingX);
            int spacingY = Math.max(totalTextHeight + dynamicSpacingY, totalTextHeight + baseSpacingY);
            
            // 在整个图片上平铺水印，从左边距50像素开始
            int startX = 50; // 左边距50像素
            for (int x = startX - watermarkedImage.getWidth(); x < watermarkedImage.getWidth() * 2; x += spacingX) {
                for (int y = -watermarkedImage.getHeight(); y < watermarkedImage.getHeight() * 2; y += spacingY) {
                    // 保存原始变换
                    AffineTransform originalTransform = g2d.getTransform();
                    
                    // 计算旋转中心点
                    int centerX = x + maxLineWidth / 2;
                    int centerY = y + totalTextHeight / 2;
                    
                    // 应用旋转-45度
                    g2d.rotate(Math.toRadians(-45), centerX, centerY);
                    
                    // 绘制多行水印文本
                    int currentY = y;
                    for (String line : watermarkLines) {
                        g2d.drawString(line, x, currentY + fontMetrics.getHeight());
                        currentY += fontMetrics.getHeight();
                    }
                    
                    // 恢复原始变换
                    g2d.setTransform(originalTransform);
                }
            }
            
        } finally {
            g2d.dispose();
        }
        
        return watermarkedImage;
    }

    /**
     * 给GIF图片添加水印
     */
    private static BufferedImage addWatermarkToGifImage(BufferedImage originalImage, String watermarkText,
                                                        String fontName, int fontSize, String colorHex,
                                                        int positionX, int positionY) {
        // GIF格式使用RGB模式
        BufferedImage watermarkedImage = new BufferedImage(
                originalImage.getWidth(), 
                originalImage.getHeight(), 
                BufferedImage.TYPE_INT_RGB
        );

        Graphics2D g2d = watermarkedImage.createGraphics();
        
        try {
            // 绘制原始图片
            g2d.drawImage(originalImage, 0, 0, null);
            
            // 设置水印样式
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, IMAGE_WATERMARK_OPACITY));

            Font font = new Font(fontName, Font.PLAIN, fontSize);
            g2d.setFont(font);
            Color color = Color.decode(colorHex);
            g2d.setColor(color);

            // 实现旋转-45度和平铺效果（与Word/Excel保持一致）
            FontMetrics fontMetrics = g2d.getFontMetrics();
            
            // 检查水印文本是否包含换行符
            String[] watermarkLines = watermarkText.split("\\n");
            
            // 计算多行文本的总高度和最大宽度
            int maxLineWidth = 0;
            int totalTextHeight = 0;
            for (String line : watermarkLines) {
                int lineWidth = fontMetrics.stringWidth(line);
                if (lineWidth > maxLineWidth) {
                    maxLineWidth = lineWidth;
                }
                totalTextHeight += fontMetrics.getHeight();
            }
            
            // 计算平铺间距
            int spacingX = maxLineWidth + IMAGE_WATERMARK_SPACING_X;
            int spacingY = totalTextHeight + IMAGE_WATERMARK_SPACING_Y;
            
            // 在整个图片上平铺水印
            for (int x = -watermarkedImage.getWidth(); x < watermarkedImage.getWidth() * 2; x += spacingX) {
                for (int y = -watermarkedImage.getHeight(); y < watermarkedImage.getHeight() * 2; y += spacingY) {
                    // 保存原始变换
                    AffineTransform originalTransform = g2d.getTransform();
                    
                    // 计算旋转中心点
                    int centerX = x + maxLineWidth / 2;
                    int centerY = y + totalTextHeight / 2;
                    
                    // 应用旋转-45度
                    g2d.rotate(Math.toRadians(-45), centerX, centerY);
                    
                    // 绘制多行水印文本
                    int currentY = y;
                    for (String line : watermarkLines) {
                        g2d.drawString(line, x, currentY + fontMetrics.getHeight());
                        currentY += fontMetrics.getHeight();
                    }
                    
                    // 恢复原始变换
                    g2d.setTransform(originalTransform);
                }
            }
            
        } finally {
            g2d.dispose();
        }
        
        return watermarkedImage;
    }

    /**
     * 给图片添加水印（通用方法）
     */
    private static BufferedImage addWatermarkToImage(BufferedImage originalImage, String watermarkText,
                                                    String fontName, int fontSize, String colorHex,
                                                    int positionX, int positionY) {
        // 根据原始图片类型创建新的图片
        // 对于支持透明度的格式使用ARGB，对于不支持透明度的格式使用RGB
        int imageType = originalImage.getTransparency() == Transparency.OPAQUE ? 
                BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        
        BufferedImage watermarkedImage = new BufferedImage(
                originalImage.getWidth(), 
                originalImage.getHeight(), 
                imageType
        );

        Graphics2D g2d = watermarkedImage.createGraphics();
        
        try {
            // 绘制原始图片
            g2d.drawImage(originalImage, 0, 0, null);
            
            // 设置水印样式
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, IMAGE_WATERMARK_OPACITY));

            Font font = new Font(fontName, Font.PLAIN, fontSize);
            g2d.setFont(font);
            Color color = Color.decode(colorHex);
            g2d.setColor(color);

            // 实现旋转-45度和平铺效果（与Word/Excel保持一致）
            FontMetrics fontMetrics = g2d.getFontMetrics();
            int textWidth = fontMetrics.stringWidth(watermarkText);
            int textHeight = fontMetrics.getHeight();

            // 计算平铺间距
            int spacingX = textWidth + IMAGE_WATERMARK_SPACING_X;
            int spacingY = textHeight + IMAGE_WATERMARK_SPACING_Y;

            // 在整个图片上平铺水印
            for (int x = -watermarkedImage.getWidth(); x < watermarkedImage.getWidth() * 2; x += spacingX) {
                for (int y = -watermarkedImage.getHeight(); y < watermarkedImage.getHeight() * 2; y += spacingY) {
                    // 保存原始变换
                    AffineTransform originalTransform = g2d.getTransform();

                    // 计算旋转中心点
                    int centerX = x + textWidth / 2;
                    int centerY = y + textHeight / 2;

                    // 应用旋转-45度
                    g2d.rotate(Math.toRadians(-45), centerX, centerY);

                    // 绘制水印文本
                    g2d.drawString(watermarkText, x, y + textHeight);
                    
                    // 恢复原始变换
                    g2d.setTransform(originalTransform);
                }
            }
            
        } finally {
            g2d.dispose();
        }
        
        return watermarkedImage;
    }

    /**
     * 根据文件扩展名获取图片格式名称
     */
    private static String getImageFormatName(String filePath) {
        String fileName = filePath.toLowerCase();
        
        if (fileName.endsWith(IMAGE_JPG) || fileName.endsWith(IMAGE_JPEG)) {
            return "jpg";
        } else if (fileName.endsWith(IMAGE_PNG)) {
            return "png";
        } else if (fileName.endsWith(IMAGE_BMP)) {
            return "bmp";
        } else if (fileName.endsWith(IMAGE_GIF)) {
            return "gif";
        } else if (fileName.endsWith(IMAGE_TIFF) || fileName.endsWith(IMAGE_TIF)) {
            return "tiff";
        } else {
            // 默认使用PNG格式
            return "png";
        }
    }

    /**
     * 给图片文件添加自定义样式的水印（完整参数版本）
     */
    private static void addCustomImageWatermark(String inputPath, String outputPath, String watermarkText,
                                               String fontName, int fontSize, String colorHex,
                                               int positionX, int positionY) {
        try {
            // 读取原始图片
            BufferedImage originalImage = ImageIO.read(new File(inputPath));
            if (originalImage == null) {
                throw new IllegalArgumentException("无法读取图片文件: " + inputPath);
            }

            // 创建带水印的图片
            BufferedImage watermarkedImage = addWatermarkToImage(originalImage, watermarkText, 
                    fontName, fontSize, colorHex, positionX, positionY);

            // 获取原始图片格式
            String formatName = getImageFormatName(inputPath);
            
            // 保存带水印的图片，保持原始格式
            ImageIO.write(watermarkedImage, formatName, new File(outputPath));

        } catch (IOException e) {
            throw new RuntimeException("自定义图片水印处理失败: " + e.getMessage(), e);
        }
    }

    /**
     * 给JPG图片添加平铺水印（旋转-45度）
     */
    private static BufferedImage addTiledWatermarkToJpgImage(BufferedImage originalImage, String watermarkText,
                                                           String fontName, int fontSize, String colorHex) {
        // JPG格式使用RGB模式，不支持透明度
        BufferedImage watermarkedImage = new BufferedImage(
                originalImage.getWidth(), 
                originalImage.getHeight(), 
                BufferedImage.TYPE_INT_RGB
        );

        Graphics2D g2d = watermarkedImage.createGraphics();
        
        try {
            // 绘制原始图片
            g2d.drawImage(originalImage, 0, 0, null);
            
            // 设置水印样式（JPG不支持透明度，使用不透明度1.0）
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));

            Font font = new Font(fontName, Font.PLAIN, fontSize);
            g2d.setFont(font);
            Color color = Color.decode(colorHex);
            g2d.setColor(color);

            // 计算水印文本的宽度和高度
            FontMetrics fontMetrics = g2d.getFontMetrics();
            int textWidth = fontMetrics.stringWidth(watermarkText);
            int textHeight = fontMetrics.getHeight();
            
            // 设置旋转角度为-45度
            g2d.rotate(Math.toRadians(ROTATION_ANGLE));

            // 计算平铺间距
            int spacingX = textWidth + 50; // X轴间距
            int spacingY = textHeight + 30; // Y轴间距

            // 平铺水印
            for (int x = -watermarkedImage.getWidth(); x < watermarkedImage.getWidth() * 2; x += spacingX) {
                for (int y = -watermarkedImage.getHeight(); y < watermarkedImage.getHeight() * 2; y += spacingY) {
                    g2d.drawString(watermarkText, x, y);
                }
            }
            
        } finally {
            g2d.dispose();
        }
        
        return watermarkedImage;
    }

    /**
     * 给PNG图片添加平铺水印（旋转-45度）
     */
    private static BufferedImage addTiledWatermarkToPngImage(BufferedImage originalImage, String watermarkText,
                                                           String fontName, int fontSize, String colorHex) {
        // PNG格式使用ARGB模式，支持透明度
        BufferedImage watermarkedImage = new BufferedImage(
                originalImage.getWidth(), 
                originalImage.getHeight(), 
                BufferedImage.TYPE_INT_ARGB
        );

        Graphics2D g2d = watermarkedImage.createGraphics();
        
        try {
            // 绘制原始图片
            g2d.drawImage(originalImage, 0, 0, null);
            
            // 设置水印样式（PNG支持透明度）
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, IMAGE_WATERMARK_OPACITY));

            Font font = new Font(fontName, Font.PLAIN, fontSize);
            g2d.setFont(font);
            Color color = Color.decode(colorHex);
            g2d.setColor(color);

            // 计算水印文本的宽度和高度
            FontMetrics fontMetrics = g2d.getFontMetrics();
            int textWidth = fontMetrics.stringWidth(watermarkText);
            int textHeight = fontMetrics.getHeight();
            
            // 设置旋转角度为-45度
            g2d.rotate(Math.toRadians(ROTATION_ANGLE));
            
            // 计算平铺间距
            int spacingX = textWidth + 50; // X轴间距
            int spacingY = textHeight + 30; // Y轴间距
            
            // 平铺水印
            for (int x = -watermarkedImage.getWidth(); x < watermarkedImage.getWidth() * 2; x += spacingX) {
                for (int y = -watermarkedImage.getHeight(); y < watermarkedImage.getHeight() * 2; y += spacingY) {
                    g2d.drawString(watermarkText, x, y);
                }
            }
            
        } finally {
            g2d.dispose();
        }
        
        return watermarkedImage;
    }

    /**
     * 给GIF图片添加平铺水印（旋转-45度）
     */
    private static BufferedImage addTiledWatermarkToGifImage(BufferedImage originalImage, String watermarkText,
                                                            String fontName, int fontSize, String colorHex) {
        // GIF格式使用RGB模式
        BufferedImage watermarkedImage = new BufferedImage(
                originalImage.getWidth(), 
                originalImage.getHeight(), 
                BufferedImage.TYPE_INT_RGB
        );

        Graphics2D g2d = watermarkedImage.createGraphics();
        
        try {
            // 绘制原始图片
            g2d.drawImage(originalImage, 0, 0, null);
            
            // 设置水印样式
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));

            Font font = new Font(fontName, Font.PLAIN, fontSize);
            g2d.setFont(font);
            Color color = Color.decode(colorHex);
            g2d.setColor(color);

            // 计算水印文本的宽度和高度
            FontMetrics fontMetrics = g2d.getFontMetrics();
            int textWidth = fontMetrics.stringWidth(watermarkText);
            int textHeight = fontMetrics.getHeight();
            
            // 设置旋转角度为-45度
            g2d.rotate(Math.toRadians(ROTATION_ANGLE));
            
            // 计算平铺间距
            int spacingX = textWidth + 50; // X轴间距
            int spacingY = textHeight + 30; // Y轴间距
            
            // 平铺水印
            for (int x = -watermarkedImage.getWidth(); x < watermarkedImage.getWidth() * 2; x += spacingX) {
                for (int y = -watermarkedImage.getHeight(); y < watermarkedImage.getHeight() * 2; y += spacingY) {
                    g2d.drawString(watermarkText, x, y);
                }
            }
            
        } finally {
            g2d.dispose();
        }
        
        return watermarkedImage;
    }

    /**
     * 给图片添加平铺水印（通用方法，旋转-45度）
     */
    private static BufferedImage addTiledWatermarkToImage(BufferedImage originalImage, String watermarkText,
                                                        String fontName, int fontSize, String colorHex) {
        // 根据原始图片类型创建新的图片
        // 对于支持透明度的格式使用ARGB，对于不支持透明度的格式使用RGB
        int imageType = originalImage.getTransparency() == Transparency.OPAQUE ? 
                BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        
        BufferedImage watermarkedImage = new BufferedImage(
                originalImage.getWidth(), 
                originalImage.getHeight(), 
                imageType
        );

        Graphics2D g2d = watermarkedImage.createGraphics();
        
        try {
            // 绘制原始图片
            g2d.drawImage(originalImage, 0, 0, null);
            
            // 设置水印样式
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, IMAGE_WATERMARK_OPACITY));

            Font font = new Font(fontName, Font.PLAIN, fontSize);
            g2d.setFont(font);
            Color color = Color.decode(colorHex);
            g2d.setColor(color);

            // 计算水印文本的宽度和高度
            FontMetrics fontMetrics = g2d.getFontMetrics();
            int textWidth = fontMetrics.stringWidth(watermarkText);
            int textHeight = fontMetrics.getHeight();
            
            // 设置旋转角度为-45度
            g2d.rotate(Math.toRadians(ROTATION_ANGLE));
            
            // 计算平铺间距
            int spacingX = textWidth + 50; // X轴间距
            int spacingY = textHeight + 30; // Y轴间距
            
            // 平铺水印
            for (int x = -watermarkedImage.getWidth(); x < watermarkedImage.getWidth() * 2; x += spacingX) {
                for (int y = -watermarkedImage.getHeight(); y < watermarkedImage.getHeight() * 2; y += spacingY) {
                    g2d.drawString(watermarkText, x, y);
                }
            }
            
        } finally {
            g2d.dispose();
        }
        
        return watermarkedImage;
    }
}
